package com.xnyzc.lhy.finance.service.impl.wallet;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xnyzc.lhy.common.entity.Qw;
import com.xnyzc.lhy.common.entity.Rv;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.util.CheckUtil;
import com.xnyzc.lhy.common.util.DateUtil;
import com.xnyzc.lhy.common.util.IDUtil;
import com.xnyzc.lhy.common.util.TokenUtil;
import com.xnyzc.lhy.finance.constant.FreezeConstant;
import com.xnyzc.lhy.finance.entity.config.OaSysCashWithdrawalConfig;
import com.xnyzc.lhy.finance.entity.order.OaCOrderPersonal;
import com.xnyzc.lhy.finance.entity.wallet.OaDFreeze;
import com.xnyzc.lhy.finance.entity.wallet.OaDWallet;
import com.xnyzc.lhy.finance.mapper.wallet.OaCOrderPersonalMapper2;
import com.xnyzc.lhy.finance.mapper.wallet.OaDFreezeMapper;
import com.xnyzc.lhy.finance.mapper.wallet.OaDWalletMapper;
import com.xnyzc.lhy.finance.service.config.IOaSysCashWithdrawalConfigService;
import com.xnyzc.lhy.finance.service.wallet.IOaDFreezeService;
import com.xnyzc.lhy.finance.service.wallet.IOaDWalletRecordService;
import com.xnyzc.lhy.finance.service.wallet.IOaDWalletService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 余额冻结表 服务实现类
 * </p>
 *
 * @author cuixiaojian
 * @since 2019-10-24
 */
@Slf4j
@Service
public class OaDFreezeServiceImpl extends ServiceImpl<OaDFreezeMapper, OaDFreeze> implements IOaDFreezeService {

    @Autowired
    private IOaSysCashWithdrawalConfigService iOaSysCashWithdrawalConfigService;

    @Autowired
    private OaDFreezeMapper oaDFreezeMapper;

    @Autowired
    private OaDWalletMapper oaDWalletMapper;

    @Autowired
    private IOaDWalletRecordService iOaDWalletRecordService;

    @Autowired
    private IOaDWalletService iOaDWalletService;

    @Autowired
    private OaCOrderPersonalMapper2 oaCOrderPersonalMapper;

    /**
     * 保存冻结金额
     * @param oaDFreeze 冻结金额信息
     * @return Map
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Rv saveFreezeBalance(OaDFreeze oaDFreeze) {

        if (CheckUtil.objIsEmpty(oaDFreeze.getFreezeAmount()) || CheckUtil.objIsEmpty(oaDFreeze.getBillTypeDesc())) {
            throw PangException.create(EErrorCode.missingArg);
        }

        oaDFreeze.setFreezeId(IDUtil.nextId());

        if (CheckUtil.objIsEmpty(oaDFreeze.getDriverId())) {
            oaDFreeze.setDriverId(TokenUtil.getTokenUserId());
        }

        if (CheckUtil.objIsEmpty(oaDFreeze.getTag())) {
            oaDFreeze.setTag(TokenUtil.getTag());
        }

        // 冻结金额抽成比，由发起账单抽成设置，暂时保留，待删除
        /*BigDecimal draw = oaDFreezeMapper.queryFreezeDraw(oaDFreeze.getOrderNumber());

        if (CheckUtil.objIsEmpty(draw)) {
            draw = BigDecimal.valueOf(0.1);
        }

        oaDFreeze.setFreezeAmount(new BigDecimal(String.valueOf((oaDFreeze.getFreezeAmount().multiply(BigDecimal.valueOf(1.00).subtract(draw))).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue())));*/

        OaSysCashWithdrawalConfig config = iOaSysCashWithdrawalConfigService.getCashWithdrawalConfig(oaDFreeze.getDriverId());
        if(CheckUtil.objIsEmpty(config)){
            throw PangException.create(EErrorCode.notConfigured);
        }
        Integer freezePeriod = config.getFreezePeriod();

        Date date = new Date();
        try {
            // 设置冻结期 ( 若设置为1天，则代表隔一天解冻，不是明天解冻而是后天解冻 )
            oaDFreeze.setFreezeDate(DateUtil.dateAddDays(date, freezePeriod + 1));
        } catch (Exception e) {
            log.error(e.getMessage());
            log.error("日期转换错误，检查参数：天数:{}，日期：{}", freezePeriod, date);
            throw PangException.create(EErrorCode.dataParseError);
        }

        oaDFreeze.setCreateUser(oaDFreeze.getDriverId());
        oaDFreeze.setCreateTime(date);
        oaDFreeze.setUpdateUser(oaDFreeze.getDriverId());
        oaDFreeze.setUpdateTime(date);

        Integer result = oaDFreezeMapper.insert(oaDFreeze);

        Integer saveWalletResult = 0;

        if (result > 0) {
            //获取乘客订单信息中的司机的费用
            OaCOrderPersonal oaCOrderPersonal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.ORDER_NO,oaDFreeze.getOrderNumber()));
            // 保存司机冻结金额
            QueryWrapper<OaDWallet> oaDWalletQueryWrapper = new QueryWrapper<>();
            oaDWalletQueryWrapper.eq(OaDWallet.DRIVER_ID, oaDFreeze.getDriverId());
            //oaDWalletQueryWrapper.select(OaDWallet.WALLET_ID, OaDWallet.WALLET_BALANCE, OaDWallet.FROZEN_BALANCE,OaDWallet.VERSION);
            OaDWallet oaDWallet = oaDWalletMapper.selectOne(oaDWalletQueryWrapper);

            if (CheckUtil.objIsEmpty(oaDWallet)) {
                throw PangException.create(EErrorCode.unWallet);
            }
            //更新加刚刚完成当前订单的金额--->冻结余额
            BigDecimal oldAmount = oaDWallet.getFrozenBalance();
            BigDecimal newAmount = oldAmount.add(oaDFreeze.getFreezeAmount());
            //更新加刚刚完成当前订单的金额--->用户余额
            BigDecimal oldWalletAmount = oaDWallet.getWalletBalance();
            BigDecimal newWalletAmount = oldWalletAmount.add(oaDFreeze.getFreezeAmount());

            oaDWallet.setFrozenBalance(newAmount);
            oaDWallet.setWalletBalance(newWalletAmount);
            //更新加上司机可提现和违规金额-->兼容处理
            if(CheckUtil.objIsNotEmpty(oaCOrderPersonal.getDriverWithdrawalProportionFee(),oaCOrderPersonal.getDriverViolationProportionFee())){
                BigDecimal driverWithdrawalProportionFee = new BigDecimal(oaCOrderPersonal.getDriverWithdrawalProportionFee());
                BigDecimal driverViolationProportionFee = new BigDecimal(oaCOrderPersonal.getDriverViolationProportionFee());
                oaDWallet.setCashBalance(oaDWallet.getCashBalance().add(driverWithdrawalProportionFee));
                oaDWallet.setFrozenBalance(oaDWallet.getFrozenBalance().add(driverViolationProportionFee));
            }

            saveWalletResult = oaDWalletMapper.updateById(oaDWallet);
            iOaDWalletRecordService.saveWalletRecord(oaDFreeze.getDriverId(),oaDFreeze.getFreezeAmount(),date,8,oaDFreeze.getOrderNumber(),"", "lhy");

        }

        Map<String, String> map = new HashMap<>();
        map.put("isSuccess", saveWalletResult.toString());

        return Rv.wrap(map);
    }

    /**
     * 清理冻结余额(解冻余额)
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Rv reFreezeBalance() {

        log.info("----------------------------------------准备解冻余额----------------------------------------------");

        List<OaDFreeze> intParam = oaDFreezeMapper.queryFreeze();
        List<Long> longList = new ArrayList<>();
        for (OaDFreeze i : intParam) {
            log.info("司机ID为：{}", i.getDriverId());
            longList.add(i.getFreezeId());
        }

        Integer result = 0;

        if (CheckUtil.collectionIsNotEmpty(intParam)) {
            result = oaDFreezeMapper.updateFreeze(longList);
        }

        List<OaDWallet> oaDWallets = new ArrayList<>();

        for (OaDFreeze oaDFreeze : intParam) {

            if (CheckUtil.collectionIsEmpty(oaDWallets)) {
                // 若集合为空，添加第一条司机解冻
                OaDWallet oaDWallet = new OaDWallet();
                oaDWallet.setDriverId(oaDFreeze.getDriverId());
                oaDWallet.setCashBalance(oaDFreeze.getFreezeAmount());
                oaDWallet.setFrozenBalance(oaDFreeze.getFreezeAmount());
                oaDWallets.add(oaDWallet);

                log.info("司机:{},增加金额:{},冻结金额:{}", oaDWallet.getDriverId(), oaDWallet.getWalletBalance(), oaDWallet.getFrozenBalance());

            } else {

                for (OaDWallet oaDWallet : oaDWallets) {

                    if (oaDWallet.getDriverId().equals(oaDFreeze.getDriverId())) {
                        // 如果存在此司机，那累加金额

                        oaDWallet.setCashBalance(oaDFreeze.getFreezeAmount().add(oaDWallet.getCashBalance()));
                        oaDWallet.setFrozenBalance(oaDFreeze.getFreezeAmount().add(oaDWallet.getFrozenBalance()));

                        log.info("存在司机---------------------------------------------------");
                        log.info("司机:{},增加金额:{},冻结金额:{}", oaDWallet.getDriverId(), oaDWallet.getWalletBalance(), oaDWallet.getFrozenBalance());
                        log.info("存在司机---------------------------------------------------");

                        break;

                    } else {
                        // 如果不存在，添加新司机

                        OaDWallet oaDWalletElement = new OaDWallet();
                        oaDWalletElement.setDriverId(oaDFreeze.getDriverId());
                        oaDWalletElement.setCashBalance(oaDFreeze.getFreezeAmount());
                        oaDWalletElement.setFrozenBalance(oaDFreeze.getFreezeAmount());
                        oaDWallets.add(oaDWalletElement);

                        log.info("司机:{},增加金额:{},冻结金额:{}", oaDWalletElement.getDriverId(), oaDWalletElement.getWalletBalance(), oaDWalletElement.getFrozenBalance());

                        break;

                    }

                }

            }

        }

        log.info("---------------------------------------------------------------------------------------------------");
        for (OaDWallet oaDWallet : oaDWallets) {
            log.info("司机:{},需要增加金额:{},需要解冻金额:{}", oaDWallet.getDriverId(), oaDWallet.getWalletBalance(), oaDWallet.getFrozenBalance());
        }
        log.info("---------------------------------------------------------------------------------------------------");

        if (CheckUtil.collectionIsNotEmpty(oaDWallets)) {

            /*QueryWrapper<OaDWallet> queryWrapper = new QueryWrapper<>();
            queryWrapper.in(OaDWallet.DRIVER_ID, oaDWallets);
            queryWrapper.select(OaDWallet.WALLET_ID, OaDWallet.DRIVER_ID, OaDWallet.WALLET_BALANCE, OaDWallet.FROZEN_BALANCE, OaDWallet.VERSION);
            List<OaDWallet> versionOaDWalletList = oaDWalletMapper.selectList(queryWrapper);*/

            List<OaDWallet> versionOaDWalletList = new ArrayList<>();

            for (OaDWallet oaDWallet : oaDWallets) {
                QueryWrapper<OaDWallet> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq(OaDWallet.DRIVER_ID, oaDWallet.getDriverId());
                queryWrapper.select(OaDWallet.WALLET_ID, OaDWallet.DRIVER_ID, OaDWallet.WALLET_BALANCE, OaDWallet.CASH_BALANCE, OaDWallet.FROZEN_BALANCE, OaDWallet.VERSION);
                OaDWallet versionOaDWallet = null;

                try {
                    versionOaDWallet = oaDWalletMapper.selectOne(queryWrapper);
                } catch (Exception e) {
                    versionOaDWallet = oaDWalletMapper.selectOne(queryWrapper);
                }

                versionOaDWalletList.add(versionOaDWallet);

            }

            for (OaDWallet versionDWallet : versionOaDWalletList) {
                log.info("钱包ID：{},司机ID：{},余额：{},冻结：{},版本：{}", versionDWallet.getWalletId(), versionDWallet.getDriverId(), versionDWallet.getWalletBalance(), versionDWallet.getFrozenBalance(), versionDWallet.getVersion());
            }

            for (OaDWallet oaDWallet : oaDWallets) {
                for (OaDWallet versionOaDWallet : versionOaDWalletList) {
                    // 拼修改格式,统一增加减少金额
                    if (versionOaDWallet.getDriverId().equals(oaDWallet.getDriverId())) {
                        log.info("开始增加钱包金额：司机：{}，增加余额：{}，减少冻结金额：{}", oaDWallet.getDriverId(), oaDWallet.getWalletBalance(), oaDWallet.getFrozenBalance());
                        // 不处理小于0的冻结记录
                        if (oaDWallet.getFrozenBalance().compareTo(BigDecimal.valueOf(0.00)) == 1) {
                            versionOaDWallet.setCashBalance(versionOaDWallet.getCashBalance().add(oaDWallet.getCashBalance()));
                            versionOaDWallet.setFrozenBalance(versionOaDWallet.getFrozenBalance().subtract(oaDWallet.getFrozenBalance()));
                        }
                        log.info("增加金额成功，司机ID：{}，所剩金额：{}，所剩冻结余额{}", versionOaDWallet.getDriverId(), versionOaDWallet.getWalletBalance(), versionOaDWallet.getFrozenBalance());
                        break;
                    }
                }
            }

            boolean esx = false;

            if (CheckUtil.collectionIsNotEmpty(versionOaDWalletList)) {
                 esx = iOaDWalletService.updateBatchById(versionOaDWalletList);
            }

            if (esx) {
                log.info("为司机解冻金额成功：", esx);
            } else {
                log.info("为司机解冻金额失败：", esx);
            }

        }

        log.info("解冻结果应成功数量：{},确认成功数量：{}", intParam.size(), result);

        log.info("----------------------------------------余额解冻完成----------------------------------------------");

        return Rv.wrap(result);

    }

    /**
     * 修改冻结金额
     * @param orderNo 订单号
     * @param driverId 司机ID
     * @param amount 修改金额
     * @return
     */
    @Override
    public Rv updateFreezeBanlance(String orderNo, Long driverId, BigDecimal amount) {

        QueryWrapper<OaDFreeze> oaDFreezeQueryWrapper = new QueryWrapper<>();
        oaDFreezeQueryWrapper.eq(OaDFreeze.DRIVER_ID, driverId);
        oaDFreezeQueryWrapper.eq(OaDFreeze.ORDER_NUMBER, orderNo);
        oaDFreezeQueryWrapper.select(OaDFreeze.FREEZZE_ID, OaDFreeze.FREEZE_AMOUNT, OaDFreeze.VERSION);

        OaDFreeze oaDFreeze = oaDFreezeMapper.selectOne(oaDFreezeQueryWrapper);

        if (CheckUtil.objIsEmpty(oaDFreeze)) {
            throw PangException.create(EErrorCode.noData);
        }

        // 判断如果金额相等，不允许修改
        if (oaDFreeze.getFreezeAmount().compareTo(amount) == 0) {
            throw PangException.create(EErrorCode.beUsed);
        }

        // 计算相差金额
        BigDecimal newAmount = amount.subtract(oaDFreeze.getFreezeAmount());

        // 设置修改金额
        oaDFreeze.setFreezeAmount(amount);
        Integer result = oaDFreezeMapper.updateById(oaDFreeze);

        if (result > 0) {
            // 修改成功
            QueryWrapper<OaDWallet> oaDWalletQueryWrapper = new QueryWrapper<>();
            oaDWalletQueryWrapper.eq(OaDWallet.DRIVER_ID, driverId);
            oaDWalletQueryWrapper.select(OaDWallet.WALLET_ID, OaDWallet.VERSION, OaDWallet.FROZEN_BALANCE, OaDWallet.WALLET_BALANCE);
            OaDWallet oaDWallet = oaDWalletMapper.selectOne(oaDWalletQueryWrapper);

            if (CheckUtil.objIsEmpty(oaDWallet)) {
                throw PangException.create(EErrorCode.noData);
            }

            oaDWallet.setWalletBalance(oaDWallet.getWalletBalance().add(newAmount));
            oaDWallet.setFrozenBalance(oaDWallet.getFrozenBalance().add(newAmount));

            Integer updateDriverWalletResult = oaDWalletMapper.updateById(oaDWallet);

            iOaDWalletRecordService.saveWalletRecord(driverId,newAmount,new Date(),FreezeConstant.UPDATE_PRISE,orderNo,"","lhy");

            return Rv.wrap(updateDriverWalletResult);

        }

        throw PangException.create(EErrorCode.unkown);
    }
}
